import { responseFormat } from 'utils/format';
import axios, { Method, AxiosRequestConfig, AxiosResponse, AxiosRequestHeaders } from 'axios'

// 定义接口
interface PendingType {
    url?: string;
    method?: Method;
    params: any;
    data: any;
    cancel: Function;
}

interface configType extends AxiosRequestConfig {
    form?: boolean,
    formUpload?: boolean
}

// 取消重复请求
const pending: Array<PendingType> = [];
const CancelToken = axios.CancelToken;

const instance = axios.create({
    baseURL: window.location.origin + '/ucc_server',
    headers: {
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': 'application/json; charset=UTF-8'
    },
    timeout: 10000,
    responseType: 'json'

})

// 移除重复请求
const removePending = (config: AxiosRequestConfig) => {
    for (const key in pending) {
        const item: number = +key;
        const list: PendingType = pending[key];
        // 当前请求在数组中存在时执行函数体
        if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
            // 执行取消操作
            list.cancel('操作太频繁，请稍后再试');
            // 从数组中移除记录
            pending.splice(item, 1);
        }
    }
};

instance.interceptors.request.use(
    (config: configType) => {
        if (localStorage.getItem('token')) {
            (config.headers as AxiosRequestHeaders)['x-access-token'] = localStorage.getItem('token') || ''
        }
        if (config.form) {
            (config.headers as AxiosRequestHeaders)['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
            delete config.form
        }
        if (config.formUpload) {
            (config.headers as AxiosRequestHeaders)['Content-Type'] = 'multipart/form-data; charset=UTF-8'
            delete config.formUpload
        }
        removePending({ ...config });
        config.cancelToken = new CancelToken((c) => {
            pending.push({ url: config.url, method: config.method as Method, params: config.params, data: config.data, cancel: c });
        });
        return config
    },
    error => {
        return Promise.reject(error)
    }
)

instance.interceptors.response.use(
    (response: AxiosResponse) => {
        removePending({ ...response.config });

        return responseFormat(response)
    },
    error => {
        return Promise.reject(error)
    }
)

export default instance